package main

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

// 部署请求结构
type DeployRequest struct {
	Name           string        `json:"name" binding:"required"`
	Image          string        `json:"image" binding:"required"`
	Replicas       int           `json:"replicas" binding:"required,min=1"`
	CPU            string        `json:"cpu" binding:"required"`
	Memory         string        `json:"memory" binding:"required"`
	Storage        *string       `json:"storage"`
	ContainerPorts []int         `json:"containerPorts" binding:"required,min=1"`
	ServiceType    string        `json:"serviceType" binding:"required"`
	PortMappings   []PortMapping `json:"portMappings" binding:"required,min=1"`
	Namespace      string        `json:"namespace" binding:"required"`
}

// 端口映射结构
type PortMapping struct {
	ContainerPort int `json:"containerPort" binding:"required"`
	ServicePort   int `json:"servicePort" binding:"required"`
}

// 部署响应结构
type DeployResponse struct {
	Success     bool   `json:"success"`
	Message     string `json:"message"`
	AppName     string `json:"app_name,omitempty"`
	Namespace   string `json:"namespace,omitempty"`
	ServiceType string `json:"service_type,omitempty"`
	Endpoints   string `json:"endpoints,omitempty"`
}

// 生成Kubernetes Deployment YAML
func generateDeploymentYAML(req *DeployRequest) string {
	// 构建容器端口配置
	var containerPorts []string
	for _, port := range req.ContainerPorts {
		containerPorts = append(containerPorts, fmt.Sprintf(`        - containerPort: %d`, port))
	}

	// 构建存储卷配置
	volumeConfig := ""
	volumeMountConfig := ""
	if req.Storage != nil && *req.Storage != "" {
		volumeConfig = fmt.Sprintf(`
      volumes:
      - name: %s-storage
        persistentVolumeClaim:
          claimName: %s-pvc`, req.Name, req.Name)

		volumeMountConfig = fmt.Sprintf(`        volumeMounts:
        - name: %s-storage
          mountPath: /data`, req.Name)
	}

	deploymentYAML := fmt.Sprintf(`apiVersion: apps/v1
kind: Deployment
metadata:
  name: %s
  namespace: %s
  labels:
    app: %s
spec:
  replicas: %d
  selector:
    matchLabels:
      app: %s
  template:
    metadata:
      labels:
        app: %s
    spec:
      containers:
      - name: %s
        image: %s
        ports:
%s
        resources:
          requests:
            cpu: %s
            memory: %s
          limits:
            cpu: %s
            memory: %s%s%s`,
		req.Name, req.Namespace, req.Name,
		req.Replicas,
		req.Name,
		req.Name,
		req.Name, req.Image,
		strings.Join(containerPorts, "\n"),
		req.CPU, req.Memory,
		req.CPU, req.Memory,
		volumeMountConfig, volumeConfig)

	return deploymentYAML
}

// 生成Kubernetes Service YAML
func generateServiceYAML(req *DeployRequest) string {
	// 构建端口映射配置
	var servicePorts []string
	for _, mapping := range req.PortMappings {
		servicePorts = append(servicePorts, fmt.Sprintf(`  - port: %d
    targetPort: %d
    protocol: TCP`, mapping.ServicePort, mapping.ContainerPort))
	}

	serviceYAML := fmt.Sprintf(`apiVersion: v1
kind: Service
metadata:
  name: %s-service
  namespace: %s
  labels:
    app: %s
spec:
  type: %s
  selector:
    app: %s
  ports:
%s`,
		req.Name, req.Namespace, req.Name,
		req.ServiceType,
		req.Name,
		strings.Join(servicePorts, "\n"))

	return serviceYAML
}

// 生成PVC YAML（如果需要存储）
func generatePVCYAML(req *DeployRequest) string {
	if req.Storage == nil || *req.Storage == "" {
		return ""
	}

	pvcYAML := fmt.Sprintf(`apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: %s-pvc
  namespace: %s
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: %s`,
		req.Name, req.Namespace, *req.Storage)

	return pvcYAML
}

// 验证部署请求
func validateDeployRequest(req *DeployRequest) error {
	// 验证应用名称（Kubernetes资源名称规范）
	if !isValidKubernetesName(req.Name) {
		return fmt.Errorf("应用名称必须符合Kubernetes命名规范：小写字母、数字和连字符，不能以连字符开头或结尾")
	}

	// 验证服务类型
	validServiceTypes := []string{"ClusterIP", "NodePort", "LoadBalancer"}
	if !contains(validServiceTypes, req.ServiceType) {
		return fmt.Errorf("无效的服务类型：%s", req.ServiceType)
	}

	// 验证端口范围
	for _, port := range req.ContainerPorts {
		if port < 1 || port > 65535 {
			return fmt.Errorf("容器端口必须在1-65535范围内：%d", port)
		}
	}

	for _, mapping := range req.PortMappings {
		if mapping.ContainerPort < 1 || mapping.ContainerPort > 65535 {
			return fmt.Errorf("容器端口必须在1-65535范围内：%d", mapping.ContainerPort)
		}
		if mapping.ServicePort < 1 || mapping.ServicePort > 65535 {
			return fmt.Errorf("服务端口必须在1-65535范围内：%d", mapping.ServicePort)
		}
	}

	return nil
}

// 检查字符串是否在切片中
func contains(slice []string, item string) bool {
	for _, s := range slice {
		if s == item {
			return true
		}
	}
	return false
}

// 验证Kubernetes资源名称
func isValidKubernetesName(name string) bool {
	if len(name) == 0 || len(name) > 63 {
		return false
	}

	// 不能以连字符开头或结尾
	if strings.HasPrefix(name, "-") || strings.HasSuffix(name, "-") {
		return false
	}

	// 只能包含小写字母、数字和连字符
	for _, char := range name {
		if !((char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '-') {
			return false
		}
	}

	return true
}

// 部署应用处理函数
func deployApplication(c *gin.Context) {
	var req DeployRequest

	// 绑定JSON请求
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"error":   "请求参数无效",
			"details": err.Error(),
		})
		return
	}

	// 验证请求
	if err := validateDeployRequest(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"error":   err.Error(),
		})
		return
	}

	// 生成Kubernetes配置
	deploymentYAML := generateDeploymentYAML(&req)
	serviceYAML := generateServiceYAML(&req)
	pvcYAML := generatePVCYAML(&req)

	// 这里应该调用Kubernetes API来实际部署
	// 目前返回模拟成功响应和生成的YAML配置

	// 构建端点信息
	endpoints := fmt.Sprintf("%s-service.%s.svc.cluster.local", req.Name, req.Namespace)
	if req.ServiceType == "NodePort" {
		endpoints += " (NodePort)"
	} else if req.ServiceType == "LoadBalancer" {
		endpoints += " (LoadBalancer)"
	}

	response := DeployResponse{
		Success:     true,
		Message:     fmt.Sprintf("应用 %s 部署成功", req.Name),
		AppName:     req.Name,
		Namespace:   req.Namespace,
		ServiceType: req.ServiceType,
		Endpoints:   endpoints,
	}

	// 在响应中包含生成的YAML配置（用于调试）
	c.JSON(http.StatusOK, gin.H{
		"success":         response.Success,
		"message":         response.Message,
		"app_name":        response.AppName,
		"namespace":       response.Namespace,
		"service_type":    response.ServiceType,
		"endpoints":       response.Endpoints,
		"deployment_yaml": deploymentYAML,
		"service_yaml":    serviceYAML,
		"pvc_yaml":        pvcYAML,
	})
}
